package com.ruoyi.system.task;

import com.aliyun.auth.credentials.Credential;
import com.aliyun.auth.credentials.provider.StaticCredentialProvider;
import com.aliyun.sdk.service.dysmsapi20170525.AsyncClient;
import com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsResponse;
import com.google.gson.Gson;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.vo.EmailVo;
import com.ruoyi.system.service.*;
import darabonba.core.client.ClientOverrideConfiguration;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 * 预警定时任务调度
 *
 * @author ruoyi
 */
@Component("warningTask")
public class WarningTask {

    @Autowired
    private IWarningRuleService warningRuleService;
    @Autowired
    EmailService emailService;
    @Autowired
    IWarningReceiverService warningReceiverService;
    @Autowired
    IPoPublicOpinionService poPublicOpinionService;
    @Autowired
    IOpinionForecastService opinionForecastService;
    @Value("${sms.accessKeyId}")
    String accessKeyId;
    @Value("${sms.accessKeySecret}")
    String accessKeySecret;
    @Value("${sms.securityToken}")
    String securityToken;
    @Value("${sms.signName}")
    String signName;
    @Value("${sms.templateCode}")
    String templateCode;




    public void ryMultipleParams(String s, Boolean b, Long l, Double d, Integer i) {
        System.out.println(StringUtils.format("执行多参方法： 字符串类型{}，布尔类型{}，长整型{}，浮点型{}，整形{}", s, b, l, d, i));
    }

    public void ryParams(String params) {
        System.out.println("执行有参方法：" + params);
        //查询预警规则
        WarningRule rule = new WarningRule();
        rule.setIsSystem(0);
        List<WarningRule> ruleList = warningRuleService.selectWarningRuleList(rule);
        for (WarningRule r:ruleList) {
           List<PoPublicOpinion> opinions= warningRuleService.getOpinionsByRule(r);
           if(opinions.size()>0){
               opinionForecastService.batchInsertOpinionForecast(opinions,r.getWarningLevel(),r.getTenantCode(),r.getId());
           }
        }

    }

    public void startWarning(String params) {
        System.out.println("执行预警任务：" + params);
        OpinionForecast forecast=new OpinionForecast();
        forecast.setStatus(0);
        List<OpinionForecast> forecasts=opinionForecastService.selectOpinionForecastList(forecast);
        forecasts.forEach(item->{
            sendWarning(item);
        });
    }

    /**
     * 发送预警
     * @param item
     */
    private void sendWarning(OpinionForecast item) {
        PoPublicOpinion opinion = poPublicOpinionService.selectPoPublicOpinionById(item.getOpinionId());
        WarningRule rule = warningRuleService.selectWarningRuleById(item.getRuleId());
        rule.getWarningTypes().forEach(type->{
            if (type.getWarningNoticeType().equals("email")) {
                sendEmail(opinion, rule.getReceivers(), rule.getWarningLevel());
            }else if (type.getWarningNoticeType().equals("sms")) {
                try {
                    sendSms(opinion, rule.getReceivers(), rule.getWarningLevel());
                }catch (ExecutionException e){
                    e.printStackTrace();
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
            }
        });


    }



    /**
     * 判断是否发送预警
     *
     * @param ids
     * @param tenantCode
     * @param level
     */

    public void sendWarning(String[] ids, String tenantCode, String level) {
        //查询系统默认预警规则
        WarningRule rule = new WarningRule();
        rule.setTenantCode(tenantCode);
        List<WarningRule> rules = warningRuleService.selectWarningRuleList(rule);
        if (rules.size() == 0) {
            //实现消息推送给app
        } else {
            for (int i = 0; i < ids.length; i++) {
                String opinionId = ids[i];
                PoPublicOpinion opinion = poPublicOpinionService.selectPoPublicOpinionById(opinionId);
                for (WarningRule r : rules) {
                    if (level.equals(r.getWarningLevel()) && conditionEmotion(opinion, r) && conditionCarrie(opinion, r) && conditionKeyWord(opinion, r)) {
                        for (int j = 0; j < r.getWarningTypes().size(); j++) {
                            RuleWarningNoticeType type = r.getWarningTypes().get(j);
                            if (type.getWarningNoticeType().equals("email")) {
                                sendEmail(opinion, r.getReceivers(),r.getWarningLevel());
                            }

                        }

                    }

                }
            }
        }


    }

    /**
     * @param opinion
     * @param r
     * @return
     */
    private boolean conditionKeyWord(PoPublicOpinion opinion, WarningRule r) {
        StringBuffer text = new StringBuffer();
        if (r.getSearchArea().equals("all")) {
            text.append(opinion.getTitle());
            text.append(opinion.getContent());
        } else if (r.getSearchArea().equals("title")) {
            text.append(opinion.getTitle());
        } else {
            text.append(opinion.getContent());
        }
        if (text.toString().contains(r.getRelatedWords())) {
            return true;
        } else {
            return false;
        }

    }

    /**
     * 判断载体
     *
     * @param opinion
     * @param rule
     * @return
     */
    private boolean conditionCarrie(PoPublicOpinion opinion, WarningRule rule) {
        List mediaTypes = rule.getMediaType();
        for (int i = 0; i < mediaTypes.size(); i++) {
            if (opinion.getCarrie().equals(mediaTypes.get(i))) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断情感
     *
     * @param opinion
     * @param rule
     * @return
     */
    private boolean conditionEmotion(PoPublicOpinion opinion, WarningRule rule) {
        List emotions = rule.getEmotion();
        for (int i = 0; i < emotions.size(); i++) {
            String e = "";
            if (opinion.getIspositive() == 1) {
                e = "positive";
            } else if (opinion.getIsneutral() == 1) {
                e = "neutral";
            } else if (opinion.getIsnegative() == 1) {
                e = "negative";
            }
            if (e.equals(emotions.get(i))) {
                return true;
            }
        }
        return false;
    }

    /**
     * 发送舆情预警（邮件）
     *
     * @param opinion
     * @param receivers
     */
    public void sendEmail(PoPublicOpinion opinion, List<RuleReceiver> receivers,String level) {

        List<String> tos = new ArrayList<>();
        if (receivers.size() == 0) {
            return;
        } else {
            receivers.forEach(receiver -> {
                Long id = receiver.getReceiver();
                WarningReceiver shou = warningReceiverService.selectWarningReceiverById(id);
                tos.add(shou.getEmail());
            });
        }

        StringBuffer content = new StringBuffer();

        content.append("<p>");

        content.append("标题：");
        content.append(opinion.getTitle());
        content.append("<br>");

        content.append("来源：");
        content.append(opinion.getSiteName());
        content.append("<br>");

        content.append("发布时间：");
        content.append(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", opinion.getPublishTime()));
        content.append("<br>");

        content.append("文章链接：");
        content.append("<a target=\"_blank\" href=\"" + opinion.getUrl() + "\" rel=\"noopener\">" + opinion.getUrl() + "</a>");
        content.append("<br>");

        content.append("</p>");

        ToolEmailConfig config = emailService.find();
        EmailVo vo = new EmailVo();
        vo.setTos(tos);
        vo.setContent(content.toString());
        vo.setSubject("监测到一条预警信息");
        emailService.send(vo, config);

        //更新预警
        OpinionForecast forecast=new OpinionForecast();
        forecast.setOpinionId(opinion.getId());
        forecast.setLevel(level);
        forecast.setStatus(1);
        opinionForecastService.updateOpinionForecast(forecast);


    }

    /**
     * 发送舆情预警（短信）
     * @param opinion
     * @param receivers
     * @param warningLevel
     */
    private void sendSms(PoPublicOpinion opinion, List<RuleReceiver> receivers, String warningLevel) throws ExecutionException, InterruptedException {


        List<String> smsList = new ArrayList<>();
        if (receivers.size() == 0) {
            return;
        } else {
            receivers.forEach(receiver -> {
                Long id = receiver.getReceiver();
                WarningReceiver shou = warningReceiverService.selectWarningReceiverById(id);
                smsList.add(shou.getPhonenumber());
            });
        }

        StringBuffer content = new StringBuffer();

        content.append("<p>");

        content.append("标题：");
        content.append(opinion.getTitle());
        content.append("<br>");

        content.append("来源：");
        content.append(opinion.getSiteName());
        content.append("<br>");

        content.append("发布时间：");
        content.append(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", opinion.getPublishTime()));
        content.append("<br>");

        content.append("文章链接：");
        content.append("<a target=\"_blank\" href=\"" + opinion.getUrl() + "\" rel=\"noopener\">" + opinion.getUrl() + "</a>");
        content.append("<br>");

        content.append("</p>");


        // Configure Credentials authentication information, including ak, secret, token
        StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder()
                .accessKeyId(accessKeyId)
                .accessKeySecret(accessKeySecret)
                .securityToken(securityToken) // use STS token
                .build());

        // Configure the Client
        AsyncClient client = AsyncClient.builder()
                .region("cn-hangzhou") // Region ID
                //.httpClient(httpClient) // Use the configured HttpClient, otherwise use the default HttpClient (Apache HttpClient)
                .credentialsProvider(provider)
                //.serviceConfiguration(Configuration.create()) // Service-level configuration
                // Client-level configuration rewrite, can set Endpoint, Http request parameters, etc.
                .overrideConfiguration(
                        ClientOverrideConfiguration.create()
                                // Endpoint 请参考 https://api.aliyun.com/product/Dysmsapi
                                .setEndpointOverride("dysmsapi.aliyuncs.com")
                        //.setConnectTimeout(Duration.ofSeconds(30))
                )
                .build();


        for (String phoneNumber:smsList) {
            // Parameter settings for API request
            SendSmsRequest sendSmsRequest = SendSmsRequest.builder()
                    .signName(signName)
                    .templateCode(templateCode)
                    .phoneNumbers(phoneNumber)
                    .templateParam("{\"code\":\"1234\"}")
                    // Request-level configuration rewrite, can set Http request parameters, etc.
                    // .requestConfiguration(RequestConfiguration.create().setHttpHeaders(new HttpHeaders()))
                    .build();

            // Asynchronously get the return value of the API request
            CompletableFuture<SendSmsResponse> response = client.sendSms(sendSmsRequest);
            // Synchronously get the return value of the API request
            SendSmsResponse resp = response.get();
            System.out.println(new Gson().toJson(resp));
            // Asynchronous processing of return values
            /*response.thenAccept(resp -> {
                System.out.println(new Gson().toJson(resp));
            }).exceptionally(throwable -> { // Handling exceptions
                System.out.println(throwable.getMessage());
                return null;
            });*/

        }

        // Finally, close the client
        client.close();


    }



    public void ryNoParams() {
        System.out.println("执行无参方法");
    }
}
